﻿#include "InpKeyWordsChecker.h"
#include "FITKAbaqusINPReader.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include <QSettings>
#include <QDebug>

namespace IO
{
    InpKeyWordsChecker::InpKeyWordsChecker(FITKAbaqusINPReader* reader)
        :_reader(reader)
    {
        _settings = new QSettings("://InpKeyWords.ini", QSettings::IniFormat);
        _allgroups = _settings->childGroups();
    }

    InpKeyWordsChecker::~InpKeyWordsChecker()
    {
        if (_settings)
            delete _settings;
    }

    bool InpKeyWordsChecker::check(const QString& header, const QStringList& keys, const QHash<QString, QString>& keyValues)
    {
        _header = header;
        _keys = keys;
        _keyValues = keyValues;
        //进行检查
        bool ok1 = checkHeader(header);
        bool ok2 = checkKeys(keys);
        bool ok3 = checkValues(keyValues);
        //结果任何一个失败就返回失败
        return ok1 && ok2 &&ok3;
    }

    bool InpKeyWordsChecker::checkHeader(const QString& header)
    {
        //全部的group
        bool c = _allgroups.contains(header);
        if (!c)
            this->unknownKeyWords(header);
        return c;
    }

    bool InpKeyWordsChecker::checkKeys(const QStringList& keys)
    {
        bool res = true;
        //文件中的关键字列表
        QString skey = _settings->value(_header + "/KeyWords").toString();
        QStringList keyList = skey.split("/");

        for (QString key : keys)
        {
            //包含关键字检查通过
           bool ok =  keyList.contains(key);
           if (ok) continue;
           res = false;
           //不支持关键字，不检查值
           unknownKeyWords(key);
           _keys.removeOne(key);
        }
        return res;
    }

    bool InpKeyWordsChecker::checkValues(const QHash<QString, QString>& keyValues)
    {
        bool res = true;

        for (QString key : _keys)
        {
            //没有值，不检查
            if(!keyValues.contains(key)) continue;
            const QString value = keyValues[key];
            //获取全部支持的值
            const QString supportValue = _settings->value(_header + "/" + key).toString();
            //  *号表示任意值都合法
            if (supportValue.simplified() == "*") continue;
            const QStringList sl = supportValue.split("/");
            //检查通过
            bool ok = sl.contains(value);
            if (ok) continue;
            ok = this->checkNums(value, sl);
            if(ok) continue;

            res = false;
            //检查不通过
            unknownKeyWords(value);
        }
        return res;
    }

    bool InpKeyWordsChecker::checkNums(QString value, QStringList supports)
    {
        do 
        {
            if (supports.contains("#Double"))
            {
                //判断是否为Double数字
                if (this->isDoubleValue(value)) return true;
                //不是double，删除支持的关键字，继续判断其他类型
                supports.removeOne("#Double");
                continue;
            }
            else if (supports.contains("#Int"))
            {
                //判断是否为Int数
                if (this->isIntValue(value)) return true;
                //不是double，删除支持的关键字，继续判断其他类型
                supports.removeOne("#Int");
                continue;
            }
            else if (supports.contains("#Float"))
            {
                //判断是否为Double数字
                if (this->isDoubleValue(value)) return true;
                //不是double，删除支持的关键字，继续判断其他类型
                supports.removeOne("#Float");
                continue;
            }
           
            return false;
        } while (true);
        return false;
    }

    bool InpKeyWordsChecker::isDoubleValue(QString value)
    {
        if (value.isEmpty()) return false;

        QString v = value.toLower();
        const bool cD = v.contains(".");
        const bool cE = v.contains("e");
        //不包含. 也不包含e 不认为是double
        if (!cD && !cE) return false;

        //负数，去掉负号判断
        bool isNeg = v.startsWith("-");
        if (isNeg)
            v = v.mid(1,v.size());
        //追加0 例如  .2转换为0.2
        if (v.endsWith(".")) v.append("0");
        //追加0 例如  2.转换为2.0
        else if (v.startsWith(".")) v.push_front("0");
        //追加0 例如  2.e-3转换为2.0e-3
        if (cD && cE)
        {
            const int indexe = v.indexOf("e");
            v.insert(indexe, "0");
        }
         
        bool ok = false;
        v.toDouble(&ok);
        return ok;
    }

    bool InpKeyWordsChecker::isIntValue(QString value)
    {
        if (value.isEmpty()) return false;
        QString v = value.toLower();
        //包含. 是double，不是int
        if (v.contains(".")) return false;
        bool ok = false;
        v.toInt(&ok);
        return ok;
    }

    void InpKeyWordsChecker::unknownKeyWords(const QString& key)
    {
        int line = -1;
        if (_reader)
            line = _reader->getCurrentLineNum()-1;
        //输出不支持关键字信息
        QString error = QString("Unknown Key Word \"%1\" at line %2").arg(key).arg(line);
        AppFrame::FITKMessageWarning(error);
        qDebug() << error;
    }



}


